package controls.sql
{	
	import com.maclema.mysql.MySqlService;
	import com.maclema.mysql.MySqlToken;
	import com.maclema.mysql.events.MySqlErrorEvent;
	import com.maclema.mysql.events.MySqlEvent;
	
	import controls.events.ServiceEvent;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.utils.Dictionary;
	
	import mx.collections.ArrayCollection;
	import mx.rpc.AsyncResponder;

	[Event(name="serviceConnected", source="controls.events.ServiceEvent")];

	public class SqlServiceCenter extends EventDispatcher
	{
		// ------------------ Public Variables ---------------- //
		public var serviceReady:Boolean;
		// ------------------ Public Variables ---------------- //
		
		// ------------------ Private Variables ----------------- //
		private static var _instance:SqlServiceCenter = null;
		private var sqlService:MySqlService;
		
		private var requests:Dictionary;
		private var pendingRequests:ArrayCollection;
		// ------------------ END Private Variables ----------------- //
		
		public function SqlServiceCenter(target:IEventDispatcher=null)
		{
			super(target);
			
			if(SqlServiceCenter._instance != null)
				throw new Error( "SqlServiceCenter is a Singleton: only one instance allowed." );
			
			initComponents();
		}
		
		// ----------------- Initialization ------------------ //
		private function initComponents():void
		{
			serviceReady = false;
			requests = new Dictionary();
			pendingRequests = new ArrayCollection();
			
			sqlService = new MySqlService();
			sqlService.hostname = "n8rand.com";
			sqlService.database = "gtcourses";
			sqlService.password = "Project123";
			sqlService.username = "gtcourses";
			
			sqlService.addEventListener(MySqlErrorEvent.SQL_ERROR, onSqlServiceError);
			sqlService.addEventListener(MySqlEvent.RESPONSE, onSqlResponse);
			sqlService.addEventListener(MySqlEvent.RESULT, onSqlResult);
			sqlService.addEventListener(Event.CONNECT, onConnect);
			sqlService.addEventListener(Event.CLOSE, onClose);
			sqlService.addEventListener(Event.ACTIVATE, onActivate);
			sqlService.addEventListener(Event.DEACTIVATE, onDeactivate);
			
			sqlService.connect();
		}
		// ----------------- END Initialization ------------------ //
		
		// ------------------ Singleton Implementation -------------- //
		public static function get instance():*
		{
			if(SqlServiceCenter._instance == null)
				SqlServiceCenter._instance = new SqlServiceCenter();
			return SqlServiceCenter._instance;
		}
		// ------------------ END Singleton Implementation --------------- //

		// -------------------- Database Request Functions ------------------ //
		public function makeDatabaseRequest(callback:Function, sql:String, 
											tokenFields:Array = null, fieldValues:Array = null, 
											errorCallback:Function = null):void
		{
			if(serviceReady)
			{
				if(!requests.hasOwnProperty(sql))
					requests[sql] = {};
				requests[sql].callback = callback;
					
				var token:MySqlToken = sqlService.send(sql);
				
				if(tokenFields != null)
				{
					for(var index:int = 0; index < tokenFields.length; index ++)
						token[tokenFields[index]] = fieldValues[index];
				}
				if(callback != null)
				{
					if(errorCallback != null)
						token.addResponder(new AsyncResponder(callback, errorCallback, token));
					else
						token.addResponder(new AsyncResponder(callback, onSqlError, token));
				}
			}
			else
			{
				pendingRequests.addItem( { sql: sql, callback: callback } );
			}
		}
		
		private function makePendingRequests():void
		{
			for each(var request:Object in pendingRequests)
				makeDatabaseRequest(request.callback, request.sql);
			pendingRequests.removeAll();
		}
		// -------------------- END Database Request Functions ------------------ //
		
		// ------------------ Event Handling ----------------- //
		private function onSqlServiceError(evt:MySqlErrorEvent):void
		{
			trace("Sql Service Error: " + evt.toString());
		}
		
		private function onSqlError(info:Object, token:MySqlToken):void
		{
			trace("Sql Error: " + info.toString());
		}
		
		private function onSqlResponse(evt:MySqlEvent):void
		{
			this.dispatchEvent(evt);
		}
		
		private function onSqlResult(evt:MySqlEvent):void
		{
			var service:MySqlService = (evt.currentTarget as MySqlService);
			var callback:Function = requests[service.lastResult].callback;
			
			callback(evt);
		}
		
		private function onActivate(evt:Event):void
		{
			trace("Active!");
		}
		
		private function onDeactivate(evt:Event):void
		{
			trace("Deactive!");
		}
		
		private function onClose(evt:Event):void
		{
			trace("Close!");
		}
		
		private function onConnect(evt:Event):void
		{
			trace("Connected!");
			serviceReady = true;
			if(pendingRequests.length > 0)
				makePendingRequests();
			this.dispatchEvent(new ServiceEvent(ServiceEvent.SERVICE_CONNECTED, true, true));
		}
		// ------------------ END Event Handling ----------------- //
		
	}
}